TalentSync

AI resume builder and ATS optimizer for job seekers. Tailored resumes, outreach, and interview prep from one profile.

Technical architecture overview

Next.js BFF, FastAPI API role, FastStream workers, Kafka, PostgreSQL. Python >=3.13. Bun on the frontend.

Repository layout#

  • Frontend: Next.js, TypeScript, Prisma client, BFF under frontend/app/api
  • Backend: FastAPI, LangChain/LangGraph, FastStream (backend/app/stream/)
  • Infra: docker-compose.yaml, docker-compose.prod.yaml, frontend/docker-compose.yaml, infra/

Building blocks#

  • Next.js: UI, Razorpay, session hydration. Rewrites /api/v1/:path* to the backend so cookies stay first-party.
  • FastAPI APP_ROLE=api: validate, meter, enqueue, job read, SSE, token streams.
  • FastAPI APP_ROLE=worker: consume lanes, run services, write job results.
  • FastAPI APP_ROLE=migrate: alembic upgrade head.
  • LLM factory: Google, OpenAI, Anthropic, Ollama, plus catalog from models.dev.
  • Two model roles: primary (LLM_*) and small (SMALL_LLM_*). Do not mix keys across user and server configs.
  • PostgreSQL: Prisma public, Alembic talentsync_backend.

How it fits together#

Frontend#

Root layout sets providers (session replacement for NextAuth, React Query, theme). getSession() in lib/session.ts verifies the access JWT with BACKEND_JWT_SECRET. Client useSession() hits /api/v1/auth/me.

Backend#

Middleware: request id, access logs, CORS. Feature routers under /api/v1. task_llm resolves BYOK vs server defaults. feature_gate debits before enqueue.

AI/ML orchestration#

Workers decrypt job.llm_config and call the same service functions the old sync routes used. No inline LLM path for metered features.

Database and Kafka#

Envelope is job_id, job_type, user_id, attempt. Payload stays in Postgres.

Dependencies#

  • Frontend: Next.js, React 18.2, Prisma, TanStack Query, Razorpay. No next-auth.
  • Backend: FastAPI, LangChain, LangGraph, Motor, PyMuPDF, FastStream >=0.7.3.
  • Infra: Postgres 16, Kafka 3.9.1 KRaft, optional Prometheus/Grafana profile.

Performance#

uv-cached backend image. Multi-stage frontend image. Small model for titles. Kafka poll interval 30 minutes so enrichments do not get kicked out of the consumer group.

Troubleshooting#

  • Missing KAFKA_BOOTSTRAP_SERVERS: workers never attach.
  • Health: API /docs, worker /health on 8001.
  • LLM test: /api/v2/llm/test still exists for provider checks.
  • NEXTAUTH_* in .env.example is leftover naming. Google OAuth settings are the ones that matter.